package com.lin.manager.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lin.manager.system.service.SysMenuService;
import com.lin.manager.system.service.SysRoleMenuService;
import com.lin.manager.common.ex.BizException;
import com.lin.manager.common.req.QueryPage;
import com.lin.manager.common.utils.TreeUtil;
import com.lin.manager.system.dao.SysMenuDao;
import com.lin.manager.system.entity.SysMenuEntity;
import com.lin.manager.system.model.vo.MenuVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @作者: 林江
 * @创建时间: 2024-03-12 12:24:04
 * @功能:
 */
@Service
public class SysMenuServiceImpl implements SysMenuService {
    @Autowired
    private SysMenuDao sysMenuDao;
    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    @Override
    public List<MenuVo> list(QueryPage page) {
        LambdaQueryWrapper<SysMenuEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByAsc(SysMenuEntity::getSorted);
        List<SysMenuEntity> list = sysMenuDao.selectList(wrapper);

        boolean flag = false;
        if (StringUtils.isNotBlank(page.getKey())) {
            flag = true;
            wrapper.like(SysMenuEntity::getName, page.getKey());
        }

        TreeUtil tree = TreeUtil.builder().parentIdName("pid").build();
        if (!flag) {
            return tree.tree(list, 0, MenuVo.class);
        } else {
            Set<Integer> ids = sysMenuDao.selectList(wrapper).stream().map(SysMenuEntity::getId).collect(Collectors.toSet());
            // 递归获取符合的元素
            for (SysMenuEntity sysMenuEntity : list) {
                if (ids.contains(sysMenuEntity.getId()) && sysMenuEntity.getId() != 0) {
                    recursion(list, sysMenuEntity.getPid(), ids);
                }
            }

            List<SysMenuEntity> data = list.stream().filter(item -> ids.contains(item.getId())).collect(Collectors.toList());
            return tree.tree(data, 0, MenuVo.class);
        }
    }

    @Override
    public void add(SysMenuEntity sysMenu) {
        checkPermission(sysMenu.getId(), sysMenu.getPermission());
        sysMenuDao.insert(sysMenu);
    }

    @Override
    public void update(SysMenuEntity sysMenu) {
        checkPermission(sysMenu.getId(), sysMenu.getPermission());
        sysMenuDao.updateById(sysMenu);
    }

    @Override
    public void del(String id) {
        sysMenuDao.deleteById(id);
        // 删除菜单关联信息
        sysRoleMenuService.deleteByMenuId(id);
    }

    @Override
    public List<SysMenuEntity> findByMenuIds(Collection<Integer> menuIds) {
        return sysMenuDao.selectList(new LambdaQueryWrapper<SysMenuEntity>().in(
                SysMenuEntity::getId, menuIds
        ));
    }

    /**
     * 权限字符必须唯一
     *
     * @param id
     * @param permission
     */
    private void checkPermission(Integer id, String permission) {
        LambdaQueryWrapper<SysMenuEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysMenuEntity::getPermission, permission);
        if (id != null) {
            wrapper.ne(SysMenuEntity::getId, id);
        }
        Long count = sysMenuDao.selectCount(wrapper);
        if (count > 0) {
            throw new BizException("权限字符已存在，请重新设置");
        }
    }

    /**
     * 递归
     *
     * @param list
     * @param pid
     * @param ids
     */
    private void recursion(List<SysMenuEntity> list, Integer pid, Set<Integer> ids) {
        for (SysMenuEntity sysMenuEntity : list) {
            if (sysMenuEntity.getId().intValue() == pid.intValue()) {
                ids.add(sysMenuEntity.getId());
                recursion(list, sysMenuEntity.getPid(), ids);
            }
        }
    }
}
